#include "GameServer.h"
#include "ui_GameServer.h"

//#include <QLinkedList>
//#include <QMessageBox>

#include <QtSql>
#include <QSqlQuery>

#define TRANSMITS_CODE_COUNT 20


DatabaseSwap::DatabaseSwap(QObject *parent):Mysql(parent)
{
    /*
    strlistSqlQuery
            << "SELECT * FROM lms_game_server_info"
            << "SELECT * FROM lms_game_user_info WHERE userid=%1 AND serverid=%2 AND serverid IN (SELECT ID FROM lms_game_server_info WHERE `key` = '%3')"
            << "SELECT * FROM lms_game_class_info"
            << "SELECT * FROM lms_game_user_class_record WHERE usergameid=%1 ORDER BY ClassID,LevelID"
            << "SELECT ID FROM lms_game_user_info WHERE NickName='%1' LIMIT 1"
            << "SELECT ID FROM lms_game_user_class_record WHERE UserGameID=%1 AND Type=%2 AND ClassID=%3 AND LevelID=%4 LIMIT 1"
            << "SELECT * FROM cmf_user WHERE user_login='%1'"
            << "UPDATE lms_game_user_info SET Score=Score+%1 WHERE ID=%2"
            << "UPDATE lms_game_user_class_record SET WordRecords='%1' WHERE ID=%2"
            << "INSERT INTO lms_game_user_score_record(usergameid,ScoreAdd) VALUES(%1,%2)"
            << "INSERT INTO lms_game_user_info(userid,serverid,NickName,Sex,Score) VALUES(%1,%2,'%3',%4,0)"
            << "INSERT INTO lms_game_user_class_record(UserGameID,ClassID,LevelID,WordRecords,Type) VALUES(%1,%2,%3,'%4',%5)"
            << "INSERT INTO cmf_user(user_login,user_nickname,user_pass,sex) VALUES('%1','%2','%3',%4)"
    ;
    */
}

DatabaseSwap::~DatabaseSwap()
{
}

int DatabaseSwap::queryUser(_ClientInfo *pClientInfo, QString password)
{
    _GameUserData* pGameUserData = (_GameUserData*)pClientInfo->m_pClientExtraData;

    if (connectDB())
    {
        QSqlQuery query(m_db);  //查询
        QString queryStr = QString("SELECT * FROM cmf_user WHERE user_login='%1'")
                .arg(pGameUserData->m_strUserName);

        if(!query.exec(queryStr))
        {
            emit s_Critical(getDB()->lastError().text());
            emit s_Critical(query.lastError().text());
            emit s_Critical(queryStr);
            query.finish();
            return -2;
        }

        //qDebug()<<query.record().count()<<query.size();
        if(query.seek(0) == false)
            return 1;

        if(password == query.value("user_pass").toString())
        {
            pGameUserData->m_unID = query.value("id").toInt();
            pGameUserData->m_nGradeID = query.value("lms_grade_id").toInt();
            //pGameUserData->m_strUserName = query.value("UserName").toString();
            query.finish();
            return 0;
        }
        else
        {
            query.finish();
            return 2;
        }
        //pGameUserData->id = query.value("ID").toUInt();
        //user.Nick = query.value("Nick").toString();
        //query.finish();
        //m_db.close();
        //return true;
    }
    else
    {
        return -1;
    }
}

int DatabaseSwap::registerUser(_ClientInfo *pClientInfo, QString password)
{
    _GameUserData* pGameUserData = (_GameUserData*)pClientInfo->m_pClientExtraData;

    if (connectDB())
    {
        QSqlQuery query(m_db);  //查询

        /*
        query.prepare("INSERT INTO UserInfo(username,nickname,password,sex) VALUES (?, ?, ?, ?)");

        QVariantList names,ages;
        names << "Tom" << "Jack" << "Jane" << "Jerry";
        ages << 20 << 23 << 22 << 25;

        //方法1:
        query.prepare("INSERT INTO User (Name, Nick, Pass) VALUES (?, ?, ?)");
        query.addBindValue(names);
        query.addBindValue(ages);

        //???不是不可以吗,要用QStringList???
        query.addBindValue(pGameUserData->m_strUserName);
        query.addBindValue(pGameUserData->m_strNickName);
        query.addBindValue(pGameUserData->password);
        query.addBindValue(pGameUserData->m_nSex);


        if (!query.execBatch())
        {
            qDebug()<<query.lastError().text();
            showError(query.lastError().text());
            return -2;
        }



        //方法2:好像不能用!?
        query.prepare("INSERT INTO User (name, age) VALUES (:name, :age)");
        //query.bindValue(":name", names);
        //query.bindValue(":age", ages);


        */



        //方法3:
        QString queryStr = QString("INSERT INTO cmf_user(user_login,user_nickname,user_pass,sex) VALUES('%1','%2','%3',%4)")
                .arg(pGameUserData->m_strUserName)
                .arg(pGameUserData->m_strNickName)
                .arg(password.replace(QChar('\''),"\'\'"))
                .arg(pGameUserData->m_nSex);
        if(!query.exec(queryStr))
        {
            if(query.lastError().number() == 1062)  //重复
            {
                query.finish();
                return 1;
            }
            emit s_Critical(getDB()->lastError().text());
            emit s_Critical(query.lastError().text());
            emit s_Critical(queryStr);
            query.finish();
            return -2;
        }
        query.finish();

        //qDebug()<<query.record().count()<<query.size();
        //m_db.close();
        return 0;
    }
    else
    {
        return -1;
    }
}

int DatabaseSwap::getGameServerInfoToBuffer(QDataStream &out)
{
    if (connectDB())
    {
        QSqlQuery query(m_db);  //查询
        QString queryStr = QString("SELECT * FROM lms_game_server_info");

        if(!query.exec(queryStr))
        {
            emit s_Critical(getDB()->lastError().text());
            emit s_Critical(query.lastError().text());
            emit s_Critical(queryStr);
            //Debug_Leamus("Query UserInfo ERROR");
            query.finish();
            return -2;
        }

        out << (qint16)INFO_SERVER_SERVERINFO_SUCCESS;

        qint16 ServerCount = 0;
        int pos = out.device()->pos();
        out << ServerCount;

        while(query.next())
        {
            out << (quint32)(query.value("ID").toInt());
            out << query.value("Name").toString();
            out << query.value("IP").toString();
            out << (quint16)(query.value("Port").toInt());
            out << query.value("Key").toString();
            ServerCount++;
            //m_GameServiceInfoList.append(QVariant::fromValue<_GameServiceInfo*>(pGameInfo));
            //m_GameServiceInfoList.insert(query.value("ID").toString(),QVariant::fromValue<ClassInfo*>(cInfo));
        }
        query.finish();
        out.device()->seek(pos);
        out << ServerCount;
        return 0;
    }
    else
    {
        return -1;
    }
}

int DatabaseSwap::getGameUserInfoToBuffer(QDataStream &out, quint32 userID, quint32 serviceID, quint32 gradeID, QString serverKey, _ClientInfo *pClientInfo)
{
    if (connectDB())
    {
        _GameUserData* pGameUserData = (_GameUserData*)pClientInfo->m_pClientExtraData;

        QSqlQuery query(m_db);  //查询
        QString queryStr = QString("SELECT * FROM lms_game_user_info WHERE userid=%1 AND serverid=%2 AND serverid IN (SELECT ID FROM lms_game_server_info WHERE `key` = '%3')")
                .arg(userID)
                .arg(serviceID)
                .arg(serverKey);

        if(!query.exec(queryStr))
        {
            emit s_Critical(getDB()->lastError().text());
            emit s_Critical(query.lastError().text());
            emit s_Critical(queryStr);
            query.finish();
            return -2;
        }

        if(query.next())
        {
            pGameUserData->m_unID = userID;
            pGameUserData->m_unUserGameID = query.value("ID").toInt();
            pGameUserData->m_strNickName = query.value("NickName").toString();
            pGameUserData->m_nSex = query.value("Sex").toInt();

            out << (qint16)GAME_SERVER_GAMEUSERINFO_SUCCESS;
            out << (quint32)pGameUserData->m_unUserGameID;
            out << pGameUserData->m_strNickName;
            out << (qint16)pGameUserData->m_nSex;
            out << (qint32)query.value("Score").toInt();
            //m_GameServiceUserInfo.tools.canReview = query.value("").to;
            //m_GameServiceUserInfo.tools.flagCorrectAnswer = query.value("").to;
            qDebug() << "[GameServer]DataBaseSwap GameUserInfo存在:" << (quint32)query.value("ID").toInt() << query.value("NickName").toString();
            query.finish();
        }
        else
        {
            qDebug() << "[GameServer]DataBaseSwap 没有此GameUserInfo:" << userID << serviceID;
            //qDebug()<<queryStr;
            query.finish();
            return 1;
        }


        //查询2种积分统计
        queryStr = QString("SELECT ScoreTotal,Type FROM lms_game_user_ranking WHERE usergameid=%1 AND serverid=%2 AND gradeid=%3 ORDER BY Type ASC")
                .arg(pGameUserData->m_unUserGameID)
                .arg(serviceID)
                .arg(gradeID);

        if(!query.exec(queryStr))
        {
            emit s_Critical(getDB()->lastError().text());
            emit s_Critical(query.lastError().text());
            emit s_Critical(queryStr);
            query.finish();
            return -2;
        }

        qint32 scoreArray[2] = {0,0};
        while(query.next())
        {
            switch(query.value("Type").toInt())
            {
            case 1:
                scoreArray[0] = (qint32)query.value("ScoreTotal").toInt();
                break;
            case 2:
                scoreArray[1] = (qint32)query.value("ScoreTotal").toInt();
                break;
            default:
                break;
            }
        }
        out << scoreArray[0];
        out << scoreArray[1];

        query.finish();

        return 0;
    }
    else
    {
        return -1;
    }
}

//将 课程信息 放入Buffer中
int DatabaseSwap::getGameClassInfoToBuffer(QDataStream &out)
{
    if (connectDB())
    {
        QSqlQuery query(m_db);  //查询
        QString queryStr = "SELECT * FROM lms_game_class_info";

        if(!query.exec(queryStr))
        {
            emit s_Critical(getDB()->lastError().text());
            emit s_Critical(query.lastError().text());
            emit s_Critical(queryStr);
            query.finish();
            return -2;
        }

        out << (qint16)GAME_SERVER_CLASSINFO_SUCCESS;

        qint16 ClassCount = 0;
        int pos = out.device()->pos();
        out << ClassCount;


        while(query.next())
        {
            out << (quint32)query.value("ID").toInt();
            out << (quint32)query.value("LevelCount").toInt();
            out << query.value("Name").toString();
            ClassCount++;
        }
        query.finish();

        out.device()->seek(pos);
        out << ClassCount;

        return 0;

    }
    else
    {
        return -1;
    }
}

int DatabaseSwap::getGameUserStudyInfoToBuffer(QDataStream &out, quint32 usergameid)
{
    //qDebug()<<"读取levelInfo:";
    if (connectDB())
    {
        QSqlQuery query(m_db);  //查询
        QString queryStr = QString("SELECT * FROM lms_game_user_class_record WHERE usergameid=%1 ORDER BY ClassID,LevelID")
                .arg(usergameid);

        if(!query.exec(queryStr))
        {
            emit s_Critical(getDB()->lastError().text());
            emit s_Critical(query.lastError().text());
            emit s_Critical(queryStr);
            query.finish();
            return -2;
        }

        out << (qint16)GAME_SERVER_STUDYINFO_SUCCESS;

        quint32 recordCount = 0;
        int pos = out.device()->pos();
        out << recordCount;

        while(query.next())
        {
            out << (quint32)query.value("ClassID").toInt();
            out << (quint32)query.value("LevelID").toInt();
            //out << (quint32)query.value("WordCount").toInt();
            out << query.value("WordRecords").toString();
            recordCount ++;
        }
        query.finish();
        out.device()->seek(pos);
        out << recordCount;


        qDebug() << "[GameServer]共:" << recordCount;
        qDebug() << "------------------";

        return 0;

    }
    else
    {
        return -1;
    }

}

int DatabaseSwap::registerGameUser( quint32 userID, quint32 serverID, QString nickName, qint16 sex, QDataStream &out, _ClientInfo *pClientInfo)
{
    if (connectDB())
    {
        QSqlQuery query(m_db);  //查询
        QString queryStr = QString("SELECT RegisterGameUser(%1,%2,'%3',%4) as ID")
                .arg(userID)
                .arg(serverID)
                .arg(nickName.replace(QChar('\''),""))
                .arg(sex)
                ;

        if(!query.exec(queryStr))
        {
            if(query.lastError().number() == 1062)  //重复
            {
                query.finish();
                return 1;
            }

            emit s_Critical(getDB()->lastError().text());
            emit s_Critical(query.lastError().text());
            emit s_Critical(queryStr);
            query.finish();
            return -2;
        }

        if(query.next())
        {
            _GameUserData* pGameUserData = (_GameUserData*)pClientInfo->m_pClientExtraData;
            pGameUserData->m_unID = userID;
            pGameUserData->m_unUserGameID = query.value("ID").toInt();
            pGameUserData->m_strNickName = nickName;
            pGameUserData->m_nSex = sex;

            out << (qint16)GAME_SERVER_REGISTERGAMEUSERINFO_SUCCESS
              << (quint32)pGameUserData->m_unUserGameID;
            query.finish();
            return 0;
        }
        else
        {
            query.finish();
            return -3;
        }

/*
        //已经注册
        if(query.next())
        {
            query.finish();
            return 1;
        }

        query.finish();



        //添加昵称Record
        queryStr = strlistSqlQuery[10]
                .arg(userID).arg(serverID).arg(nickName).arg(sex);
        if(!query.exec(queryStr))
        {
            emit s_Critical(getDB()->lastError().text());
            emit s_Critical(query.lastError().text());
            emit s_Critical(queryStr);
            query.finish();
            return -3;
        }
        query.finish();


        queryStr = strlistSqlQuery[4]
                .arg(nickName);

        if(!query.exec(queryStr))
        {
            emit s_Critical(getDB()->lastError().text());
            emit s_Critical(query.lastError().text());
            emit s_Critical(queryStr);
            query.finish();
            return -4;
        }

        if(query.next())
        {
            _GameUserData* pGameUserData = (_GameUserData*)pClientInfo->m_pClientExtraData;
            pGameUserData->m_unUserGameID = query.value("ID").toInt();
            pGameUserData->m_strNickName = nickName;
            pGameUserData->m_nSex = sex;

            out << (qint16)GAME_SERVER_REGISTERGAMEUSERINFO_SUCCESS
              << (quint32)query.value("ID").toInt();
            query.finish();
            return 0;
        }
        else
        {
            query.finish();
            return -5;
        }
        */

        /*/*
        ////添加经验Record
        sql = QString("INSERT INTO GameUserScoreInfo(usergameid,score) VALUES(%1,0)").arg(m_LoginInfo.id);
        if(!query.exec(sql))
        {
            emit s_Critical(getDB()->lastError().text());
            emit s_Critical(query.lastError().text());
            emit s_Critical(queryStr);
            query.finish();
            return -1;
        }
        query.finish();* /*/
    }
    else
    {
        return -1;
    }
}
qint16 DatabaseSwap::saveUserStudyResult(quint32 userGameID
                                      , quint32 classID, quint32 levelID
                                      , QString result)
{
    //qDebug()<<"saveUserStudyResult";
    if (connectDB())
    {
        QSqlQuery query(m_db);  //查询
        QString queryStr;

        //查询对应的ID
        queryStr = QString("CALL SaveGameUserStudyResult(%1,%2,%3,%4,'%5')")
                .arg(userGameID).arg(0).arg(classID).arg(levelID).arg(result);

        if(!query.exec(queryStr))
        {
            emit s_Critical(getDB()->lastError().text());
            emit s_Critical(query.lastError().text());
            emit s_Critical(queryStr);
            query.finish();
            return -2;
        }

        switch (query.numRowsAffected()) {
        case 0:     //更新(0表示和原来的值相同)
        case 2:
            query.finish();
            return 0;
        case 1:     //插入
            query.finish();
            return 1;
        default:
            query.finish();
            return -3;
        }
    }
    return -1;
}
/*
qint16 DatabaseSwap::saveUserStudyResult(quint32 userGameID
                                      , qint16 type, quint32 classID, quint32 levelID
                                      , quint32 wordCount, QString result, bool newLevel)
{
    //qDebug()<<"saveUserStudyResult";
    if (connectDB())
    {
        QSqlQuery query(m_db);  //查询
        QString queryStr;
        int nRecordID = 0;

        //查询对应的ID
        queryStr = strlistSqlQuery[5]
                .arg(userGameID).arg(type).arg(classID).arg(levelID);

        if(!query.exec(queryStr))
        {
            emit s_Critical(getDB()->lastError().text());
            emit s_Critical(query.lastError().text());
            emit s_Critical(queryStr);
            query.finish();
            return -2;
        }

        //如果存在记录
        if(query.next())
        {
            nRecordID = query.value("ID").toInt();
            newLevel = false;
            query.finish();
        }
        //如果不存在,且 不新加 也不是 第一关
        else if(levelID != 0 && newLevel == false)
        {
            showError(query.lastError().text());
            Debug(query.lastError().text());
            Debug(queryStr);
            query.finish();
            return -5;
        }
        else    //新增记录(1.newLevel为true; 2.没记录但是第1关)
        {
            newLevel = true;
            query.finish();
        }

        if(newLevel)     //第一关有这种情况，新插入记录
        {
            queryStr = strlistSqlQuery[11]
                    .arg(userGameID).arg(classID).arg(levelID).arg(wordCount).arg(result).arg(type);

            if(!query.exec(queryStr))
            {
                emit s_Critical(getDB()->lastError().text());
                emit s_Critical(query.lastError().text());
                emit s_Critical(queryStr);
                query.finish();
                return -3;
            }
            query.finish();
            return 1;
        }
        else    //更新记录
        {
            queryStr = strlistSqlQuery[8]
                    .arg(result).arg(nRecordID);

            if(!query.exec(queryStr))
            {
                emit s_Critical(getDB()->lastError().text());
                emit s_Critical(query.lastError().text());
                emit s_Critical(queryStr);
                query.finish();
                return -4;
            }
            query.finish();
            return 0;
        }
    }
    return -1;
}
*/

int DatabaseSwap::getGameUserRankingToBuffer(QDataStream &out, quint32 serverID, quint32 gradeID)
{
    if (connectDB())
    {
        QSqlQuery query(m_db);  //查询
        QString queryStr = QString("CALL GameRanking(%1,%2)")
                .arg(serverID).arg(gradeID);

        if(!query.exec(queryStr))
        {
            emit s_Critical(getDB()->lastError().text());
            emit s_Critical(query.lastError().text());
            emit s_Critical(queryStr);
            query.finish();
            return -2;
        }

        out << (qint16)GAME_SERVER_RANKING_SUCCESS;

        qint16 count = 0;
        int pos = out.device()->pos();
        out << count;


        while(query.next())
        {
            out << (quint32)query.value("usergameid").toInt();
            out << (quint32)query.value("Type").toInt();
            out << query.value("NickName").toString();
            out << (qint32)query.value("ScoreTotal").toInt();
            out << (qint32)query.value("Score").toInt();
            count++;
        }
        query.finish();

        out.device()->seek(pos);
        out << count;

        return 0;

    }
    else
    {
        return -1;
    }
}


int DatabaseSwap::getGameUserItemsToBuffer(QDataStream &out, _GameUserData* pGameUserData, quint32 serverID)
{
    if (connectDB())
    {
        QSqlQuery query(m_db);  //查询
        QString queryStr = QString("SELECT * FROM lms_users_items WHERE userid = %1 AND serverid = %2")
                .arg(pGameUserData->m_unID)
                .arg(serverID);

        if(!query.exec(queryStr))
        {
            emit s_Critical(getDB()->lastError().text());
            emit s_Critical(query.lastError().text());
            emit s_Critical(queryStr);
            query.finish();
            return -2;
        }

        out << (qint16)GAME_SERVER_ITEMS_SUCCESS;

        qint16 count = 0;
        int pos = out.device()->pos();
        out << count;


        while(query.next())
        {
            qint16 status = 0;
            QDateTime dt = query.value("requireDateTime").toDateTime();
            if(QDateTime::currentDateTime() < dt)
                status = 1;

            out << (quint32)query.value("id").toInt();
            out << (qint32)query.value("type").toInt();
            out << (qint32)query.value("value").toInt();
            out << status;
            out << query.value("addDateTime").toDateTime();
            out << dt;
            count++;
        }
        query.finish();

        out.device()->seek(pos);
        out << count;

        return 0;

    }
    else
    {
        return -1;
    }
}

int DatabaseSwap::updateUserScore(quint32 userGameID, qint32 scoreAdd)
{
    //qDebug()<<"updateUserScore";

    if (connectDB())
    {
        QSqlQuery query(m_db);  //查询
        QString queryStr;

        queryStr = QString("CALL UpdateGameUserScoreInfo(%1,%2);")
                .arg(userGameID).arg(scoreAdd);

        if(!query.exec(queryStr))
        {
            emit s_Critical(getDB()->lastError().text());
            emit s_Critical(query.lastError().text());
            emit s_Critical(queryStr);
            query.finish();
            return -2;
        }


        /*
        queryStr = strlistSqlQuery[7]
            .arg(scoreAdd).arg(userGameID);

        if(!query.exec(queryStr))
        {
            emit s_Critical(getDB()->lastError().text());
            emit s_Critical(query.lastError().text());
            emit s_Critical(queryStr);
            query.finish();
            return -3;
        }
        */

        query.finish();
        return 0;
    }
    else
    {
        return -1;
    }
}

int DatabaseSwap::insertUserOnlineLog(quint32 userGameID, qint16 clientType, QDateTime dtLogin, QDateTime dtLogout)
{
    //qDebug()<<"updateUserScore";

    if (connectDB())
    {
        QSqlQuery query(m_db);  //查询
        QString queryStr;

        queryStr = QString("INSERT INTO lms_game_user_onlineLog(usergameid,ClientType,loginDateTime,logoutDateTime) VALUES(%1,%2,'%3','%4');")
                .arg(userGameID)
                .arg(clientType)
                .arg(dtLogin.toString("yyyy-MM-dd hh:mm:ss"))
                .arg(dtLogout.toString("yyyy-MM-dd hh:mm:ss"));

        if(!query.exec(queryStr))
        {
            emit s_Critical(getDB()->lastError().text());
            emit s_Critical(query.lastError().text());
            emit s_Critical(queryStr);
            query.finish();
            return -2;
        }


        /*
        queryStr = strlistSqlQuery[7]
            .arg(scoreAdd).arg(userGameID);

        if(!query.exec(queryStr))
        {
            emit s_Critical(getDB()->lastError().text());
            emit s_Critical(query.lastError().text());
            emit s_Critical(queryStr);
            query.finish();
            return -3;
        }
        */

        query.finish();
        return 0;
    }
    else
    {
        return -1;
    }
}
















int _GameGroup::StartGame()
{
    if(m_pClientsGroupInfo->m_listClients.isEmpty())
        return -1;

    if(m_pClientsGroupInfo->m_flagStatus & _ClientsGroupInfo::Status_Locked)
        return -2;

    //int userCount = m_listClients.count();

    //是否可以开始游戏
    QList<_ClientInfo*>::const_iterator ii;
    for(ii = m_pClientsGroupInfo->m_listClients.constBegin(); ii != m_pClientsGroupInfo->m_listClients.constEnd(); ++ii)
    {
        if(((_GameUserData*)((*ii)->m_pClientExtraData))->m_GameStatus != _ClientGameStatus::Game_Readying)
        {
            emit s_Debug(_T("[GameGroup]有人没准备好"));
            return -3;
        }
    }



    emit s_Debug(_T("[GameGroup]可以开始游戏"));
    //Debug(_T("[GameGroup]随机数种子:%1").arg(lmsSrand(-1)));
    /*
     * 1.设置每个用户status
     * 2.设置游戏status
     * 3.设置Master
     * 4.发送m_nMyID(GameID),玩家数,角色,武将信息!!!???
    */

    //QList<_Player::JiaoSe> playerJiaoSeList;  //GameID代替了

    //设置变量
    m_pClientsGroupInfo->m_flagStatus |= _ClientsGroupInfo::Status_Locked;
    m_nPlayerCount = m_pClientsGroupInfo->m_GroupInfo.nClientsMaxCount;
    m_bMaster = true;
    m_nMyID = -1;


    //QVector<quint32> playerGameIDArray(m_nPlayerCount);
    //QVector<qint16> playerDuiWuArray(m_nPlayerCount);

    //随机排列位置,设置角色
    qint32 temp[GAME_MAX_NUM_PLAYER];
    if(!GetDifferentNumber(0,m_nPlayerCount,temp,m_nPlayerCount,sizeof(qint32)))
    {
        m_pClientsGroupInfo->m_flagStatus = _ClientsGroupInfo::Status_Normal;
        return -1;
    }


    //发送
    QByteArray ba = m_pClientsGroupInfo->m_pIOCP->newSendData(0x10);
    QDataStream ds(&ba,QIODevice::ReadWrite);
    ds.device()->seek(ba.size());
    ds << (qint16)GAME_SERVER_RESPONSE
       << (qint16)GAME_SERVER_STARTGAME
       << (qint16)GAME_SERVER_STARTGAME_SUCCESS
       << (qint16)m_nPlayerCount
       //<< playerGameIDArray
       //<< playerDuiWuArray
       //<< playerJiaoSeList
          ;
    /*
    int jjj;
    QString tStr = QString("座位%1:").arg(m_nPlayerCount);;
    for(jjj = 0; jjj < m_nPlayerCount; jjj++)
        tStr += QString("%1,").arg(temp[jjj]);
    emit s_Debug(tStr);
    */


    int userCount = m_pClientsGroupInfo->m_listClients.count();
    for(int i = 0; i < m_nPlayerCount; i++)
    {
        if(temp[i] < userCount)       //前几人是 玩家
        {
            _GameUserData* m_pClientExtraData = (_GameUserData*)(m_pClientsGroupInfo->m_listClients.at(temp[i])->m_pClientExtraData);
            m_pClientExtraData->m_nPlayID = i;   //玩家下标

            m_arrayPlayer[i].m_eJiaoSe = _Player::JiaoSe_Others;
            m_arrayPlayer[i].m_nDuiWu = m_pClientExtraData->m_nDuiWu;
            //playerGameIDArray[i] = ((_GameUserData*)(m_pClientsGroupInfo->m_listClients.at(i)->m_pClientExtraData))->m_unUserGameID;
            //playerDuiWuArray[i] = ((_GameUserData*)(m_pClientsGroupInfo->m_listClients.at(i)->m_pClientExtraData))->m_nDuiWu;
            ds << (qint16)temp[i];        //没用
            ds << m_pClientExtraData->m_unUserGameID;
            ds << m_pClientExtraData->m_strNickName;
            ds << m_pClientExtraData->m_nDuiWu;
            //playerJiaoSeList.append(_Player::JiaoSe_Others);
        }
        else    //后几人都是电脑
        {
            m_arrayPlayer[i].m_eJiaoSe = _Player::JiaoSe_AI;
            m_arrayPlayer[i].m_nDuiWu = (i + 10);      //!!!电脑队伍10以上
            //playerGameIDArray[i] = 0;
            //playerDuiWuArray[i] = n + 10;     //电脑是10以上
            ds << (qint16)temp[i];        //没用
            ds << (quint32)0;
            ds << QString("");
            ds << (qint16)m_arrayPlayer[i].m_nDuiWu;
            //playerJiaoSeList.append(_Player::JiaoSe_AI);
        }

    }

    m_pClientsGroupInfo->m_pIOCP->CorrectDataLength(ba);
    m_pClientsGroupInfo->SendToGroupAllClients(ba, nullptr);
    //sendToAllClientInGroup(ba, pClientInfo);

    //qDebug() << "[GameGroup]playerGameIDArray:" << playerGameIDArray;
    emit s_Debug(_T("[GameGroup]游戏开始数据群发完毕,等待客户Init后开始游戏线程"));

    return 0;
}


int _GameGroup::GameOver()
{
    return GameCore::GameOver();
}








GameCore::_GameButtonValue _GameGroup::ChuPai(int player,_GameChuPaiType nType, int nValue, int nParam1, int nParam2, QVariant nParam3, int nInitStep, QString strMsg)
{
    _GameButtonValue ret = Game_Button_ERROR;

    qDebug() << "[GameServer]GameGroup 出牌处理中...";
    //是 电脑出牌
    if(m_arrayPlayer[player].isComputer())
    {
        ret = GameCore::ChuPai(player,nType,nValue,nParam1,nParam2,nParam3,nInitStep,strMsg);

        QByteArray ba = m_pClientsGroupInfo->m_pIOCP->newSendData(0x20);
        QDataStream ds(&ba,QIODevice::ReadWrite);
        ds.device()->seek(ba.size());

        //本人出牌,发送数据
        ds<<(qint16)GAME_DATA<<(qint16)GAME_DATA_TRANSFER_CHUPAI
                        <<(qint16)ret<<(qint16)(sizeof(PokeStep) * m_nStepCount);
        ds.writeRawData((const char*)m_arrayStep,(sizeof(PokeStep) * m_nStepCount));

        m_pClientsGroupInfo->m_pIOCP->CorrectDataLength(ba);
        emit s_SendToGroupAllClients(ba,nullptr);
        qDebug() << "[GameServer]GameGroup 电脑出牌完毕并发送";
    }

    else
    //(m_arrayPlayer[player].IsOtherPlayer() || (m_bMaster == false && m_arrayPlayer[player].IsComputer()))
    {
        qDebug() << "[GameServer]GameGroup 等待出牌";
        _GameData *pData = (_GameData*)m_Producer.safeOut();
        if(CheckGameOver() != Game_Status_Continue)
        {
            if(pData != nullptr)delete pData;
            return Game_Button_ERROR;
        }

        if(pData == nullptr)
        {
            emit s_Critical(_T("[!GameGroup]ChuPai同步ERROR:pData为nullptr"));
            setGameStatus(Game_Status_ERROR);
            return Game_Button_ERROR;
        }
        if(pData->type != GAME_DATA_TRANSFER_CHUPAI)
        {
            emit s_Critical(_T("[!GameGroup]ChuPai同步ERROR:类型错误(%1)").arg(pData->type));
            delete pData;
            setGameStatus(Game_Status_ERROR);
            return Game_Button_ERROR;
        }
        if(((_GameUserData*)((_ClientInfo*)pData->sender)->m_pClientExtraData)->m_nPlayID != player)
        {
            emit s_Critical(_T("[GameServer]GameGroup ChuPai同步ERROR:发送者错误:(%1,%2)")
                  .arg(((_GameUserData*)((_ClientInfo*)pData->sender)->m_pClientExtraData)->m_nPlayID)
                  .arg(player)
                  );
            delete pData;
            setGameStatus(Game_Status_ERROR);
            return Game_Button_ERROR;
        }


        QByteArray ba = m_pClientsGroupInfo->m_pIOCP->newSendData(0x20);
        QDataStream ds(&ba,QIODevice::ReadWrite);
        ds.device()->seek(ba.size());

        ds << (qint16)GAME_DATA << (qint16)GAME_DATA_TRANSFER_CHUPAI
                        << (qint16)pData->ChuPaiData.nData<<pData->ChuPaiData.nDataLength;
        ds.writeRawData(pData->ChuPaiData.pData,pData->ChuPaiData.nDataLength);

        m_pClientsGroupInfo->m_pIOCP->CorrectDataLength(ba);
        emit s_SendToGroupAllClients(ba,(_ClientInfo*)pData->sender);
        qDebug() << "[GameServer]GameGroup 转发出牌信息完毕";



        memcpy(m_arrayStep,pData->ChuPaiData.pData,pData->ChuPaiData.nDataLength);
        ret = (_GameButtonValue)pData->ChuPaiData.nData;
        delete pData;

    }
    //stopChuPai(player);
    return ret;
}


int _GameGroup::ShaiDian()
{
    qDebug() << "[GameServer]GameGroup 骰点数据处理中...";
    qint32 n;
    //if(m_bMaster)
    {
        n = GameCore::ShaiDian();


        QByteArray ba = m_pClientsGroupInfo->m_pIOCP->newSendData(0x20);
        QDataStream ds(&ba,QIODevice::ReadWrite);
        ds.device()->seek(ba.size());

        ds<<(qint16)GAME_DATA<<(qint16)GAME_DATA_TRANSFER_RANDOM<<n;

        m_pClientsGroupInfo->m_pIOCP->CorrectDataLength(ba);
        emit s_SendToGroupAllClients(ba, nullptr);


        qDebug() << "[GameServer]GameGroup 骰点发送完毕:" << n;

    }
    return n;
}


bool _GameGroup::Game_CreateWenTiAndSend(qint32 wordID[4], qint16 nAnswer)
{
    //!!!得到单词
    qDebug() << "[GameServer]GameGroup 准备问题中...";

    qint32 temp[4];   //临时用temp的0和1作为起始和终止
    switch(this->m_unClassID)
    {
    case 1:
        temp[0] = 1;
        temp[1] = 461;
        break;
    case 2:
        temp[0] = 461;
        temp[1] = 861;
        break;
    case 3:
        temp[0] = 861;
        temp[1] = 1341;
        break;
    case 4:
        temp[0] = 1341;
        temp[1] = 1821;
        break;
    case 5:
        temp[0] = 1821;
        temp[1] = 2501;
        break;
    case 6:
        temp[0] = 2501;
        temp[1] = 4181;
        break;
    case 7:
        temp[0] = 4181;
        temp[1] = 8861;
        break;
    case 8:
        temp[0] = 8861;
        temp[1] = 10321;
        break;

    default:
        temp[0] = 1;
        temp[1] = 10321;
        break;
    }

    if(!GetDifferentNumber(temp[0],temp[1],temp,4,sizeof(qint32)))
    {
        setGameStatus(Game_Status_ERROR);
        return false;
    }

    for(int i = 0; i < 4; i++)
        wordID[i] = temp[i];



    QByteArray ba = m_pClientsGroupInfo->m_pIOCP->newSendData(0x20);
    QDataStream ds(&ba,QIODevice::ReadWrite);
    ds.device()->seek(ba.size());

    ds << (qint16)GAME_DATA << (qint16)GAME_DATA_TRANSFER_WENTI <<
          wordID[0] << wordID[1] << wordID[2] << wordID[3] << nAnswer;

    m_pClientsGroupInfo->m_pIOCP->CorrectDataLength(ba);
    emit s_SendToGroupAllClients(ba, nullptr);
    qDebug() << "[GameServer]GameGroup 发送问题完毕";

    return true;

}

bool _GameGroup::WenTi(int player, QString msg, int time)
{
    bool answer = false;

    qint32 wordID[4] = {1,2,3,4};
    qint16 nAnswer = (qint16)Random(0,4);

    if(!Game_CreateWenTiAndSend(wordID, nAnswer))
    {
        setGameStatus(Game_Status_ERROR);
        return false;
    }

    if(m_arrayPlayer[player].isComputer())
    {
        int choice;
        if(qrand() % 2 == 0)
            choice = nAnswer;
        else
            choice = qrand() % 4;

        answer = (choice == nAnswer);


        QByteArray ba = m_pClientsGroupInfo->m_pIOCP->newSendData(0x20);
        QDataStream ds(&ba,QIODevice::ReadWrite);
        ds.device()->seek(ba.size());

        ds << (qint16)GAME_DATA << (qint16)GAME_DATA_TRANSFER_ANSWER
                        << (qint16)choice;

        m_pClientsGroupInfo->m_pIOCP->CorrectDataLength(ba);
        emit s_SendToGroupAllClients(ba, nullptr);

        qDebug() << "[GameServer]GameGroup 发送答案完毕";

    }
    else
    {
        qDebug() << "[GameServer]GameGroup 等待回答问题...";
        _GameData *pData = (_GameData*)m_Producer.safeOut();
        if(CheckGameOver() != Game_Status_Continue)
        {
            if(pData != nullptr)delete pData;
            return false;
        }


        if(pData == nullptr)
        {
            emit s_Critical(_T("[!GameGroup]Answer同步ERROR:pData为nullptr"));
            setGameStatus(Game_Status_ERROR);
            return Game_Button_ERROR;
        }
        if(pData->type != GAME_DATA_TRANSFER_ANSWER)
        {
            emit s_Critical(_T("[!GameGroup]Answer同步ERROR:类型错误(%1)").arg(pData->type));
            delete pData;
            setGameStatus(Game_Status_ERROR);
            return Game_Button_ERROR;
        }
        if(((_GameUserData*)((_ClientInfo*)pData->sender)->m_pClientExtraData)->m_nPlayID != player)
        {
            emit s_Critical(_T("[!GameGroup]Answer同步ERROR:发送者错误:(%1,%2)")
                  .arg(((_GameUserData*)((_ClientInfo*)pData->sender)->m_pClientExtraData)->m_nPlayID)
                  .arg(player)
                  );
            delete pData;
            setGameStatus(Game_Status_ERROR);
            return Game_Button_ERROR;
        }


        answer = (pData->nAnswer == nAnswer);


        QByteArray ba = m_pClientsGroupInfo->m_pIOCP->newSendData(0x20);
        QDataStream ds(&ba,QIODevice::ReadWrite);
        ds.device()->seek(ba.size());

        ds << (qint16)GAME_DATA << (qint16)GAME_DATA_TRANSFER_ANSWER
                        << (qint16)pData->nAnswer;

        m_pClientsGroupInfo->m_pIOCP->CorrectDataLength(ba);
        emit s_SendToGroupAllClients(ba,(_ClientInfo*)pData->sender);
        qDebug() << "[GameServer]GameGroup 发送答案完毕";


        delete pData;
    }

    return answer;
}




















GameServer::GameServer(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::GameServer)
{
    ui->setupUi(this);
    ui->pushButtonClose->setEnabled(false);
    this->setWindowTitle("英语杀服务器  --made by 深林孤鹰");

    //ui->textDebug->document()->setMaximumBlockCount();


    //要在 信号/槽/属性 的参数中使用，或者qml中使用下列类型的函数或数据，则注册一下！字符串名不能随意更改!
    /*
     * 1.enum类型:
     *      如果信号槽的参数要使用Q_ENUMS或Q_FLAGS,需要注册一下!
     *      注册方法:如果有 类前缀,参数中不能使用 类前缀!!!比如只能:
     *          qRegisterMetaType<[类名::]enum名>("enum名");
     * 2.类 类型:
     *      QML中需要使用其类的函数,或信号槽的参数中需要使用其类型,则需要注册一下:
     *      注册方法:如果有 类前缀,参数中必须要有 类前缀!!!比如:
     *          qRegisterMetaType<[类名::]类名>("[类名::]类名");
    */
    qRegisterMetaType<QObjectList>("QObjectList");      //qml中使用其函数
    qRegisterMetaType<_BaseObject::_ObjType>("_ObjType");  //信号/槽参数中使用
    qRegisterMetaType<_BaseObject::_Flags>("_Flags");
    //qRegisterMetaType<GameCore::_GameButtonValue>("_GameButtonValue");
    qRegisterMetaType<GameCore::_GameStatus>("_GameStatus");
    qRegisterMetaType<_ClientGameStatus>("_ClientGameStatus");



    m_DatabaseSwap.getMySqlInfo()["HostName"] = m_Server.m_vmapConfig["HostName"].toString();
    m_DatabaseSwap.getMySqlInfo()["DatabaseName"] = m_Server.m_vmapConfig["DatabaseName"].toString();
    m_DatabaseSwap.getMySqlInfo()["UserName"] = m_Server.m_vmapConfig["UserName"].toString();
    m_DatabaseSwap.getMySqlInfo()["Password"] = m_Server.m_vmapConfig["Password"].toString();



    m_Server.m_nRecievedDataMaxSize = 100 * 1024;   //100K
    m_Server.m_poolClientsGroupInfo.m_nReserveCount = 10;

    m_Server.m_IOCPModel.SetServerIP("0.0.0.0");
    m_Server.m_IOCPModel.SetWatchThreadInterval(30000);
    m_Server.m_IOCPModel.SetIOCPFlag(1);
    m_Server.m_IOCPModel.SetHeartData("H",1);
    m_Server.m_IOCPModel.m_baPackageHeaderFlag.setRawData("LMS",3);
    m_Server.m_IOCPModel.SetIOCPCountProperty(-1,SOMAXCONN,10,10);

    m_Server.m_IOCPModel.SetIOCPSetSocketExtraDataCallback((void*)Fn_IOCP_SetSocketExtraData_Callback);
    m_Server.m_IOCPModel.SetIOCPUnsetSocketExtraDataCallback((void*)Fn_IOCP_UnsetSocketExtraData_Callback);
    m_Server.m_IOCPModel.SetIOCPInitSocketExtraDataCallback((void*)Fn_IOCP_Init_SocketExtraData_Callback);
    m_Server.m_IOCPModel.SetIOCPReleaseSocketExtraDataCallback((void*)Fn_IOCP_Release_SocketExtraData_Callback);


    //设置四种回调函数
    _ClientsGroupInfo::SetGroupExtraDataCallback = Fn_SetGroupExtraData_Callback;
    _ClientsGroupInfo::UnsetGroupExtraDataCallback = Fn_UnsetGroupExtraData_Callback;
    _ClientsGroupInfo::InitGroupExtraDataCallback = Fn_InitGroupExtraData_Callback;
    _ClientsGroupInfo::ReleaseGroupExtraDataCallback = Fn_ReleaseGroupExtraData_Callback;


    lmsSrand(-1);



    connect(&m_Server,&Server::s_Debug,this,&GameServer::Debug,Qt::QueuedConnection);
    connect(&m_Server,&Server::s_Critical,this,&GameServer::Critical,Qt::QueuedConnection);
    //connect(&m_Server,&Server::s_ReadyRead,this,&Server::onReadyRead,Qt::DirectConnection);
    connect(&m_Server,&Server::s_ReadyRead,this,&GameServer::onReadyRead,Qt::QueuedConnection);
    connect(&m_Server,&Server::s_Accept,this,&GameServer::onAccept,Qt::QueuedConnection);
    connect(&m_Server,&Server::s_Disconnect,this,&GameServer::onDisconnect,Qt::QueuedConnection);



    connect(ui->pushButtonStart,&QPushButton::clicked,this,[=](){
        if(!Start())
        {
            Stop();
            return;
        }

        ui->pushButtonStart->setEnabled(false);
        ui->pushButtonClose->setEnabled(true);
    });

    connect(ui->pushButtonClose,&QPushButton::clicked,this,[=](){
        Stop();

        ui->pushButtonStart->setEnabled(true);
        ui->pushButtonClose->setEnabled(false);
    });

    connect(ui->pushButtonUserList,&QPushButton::clicked,this,[=](){

        QMap<void*,_ClientInfo*>::const_iterator ii;
        for(ii = m_mapAllClients.constBegin(); ii != m_mapAllClients.constEnd(); ii++)
        {
            Debug(_T("用户%1(%2):%3").arg((int)(ii.value()->m_SocketContext.nSocketID)).arg((int)(ii.value()->m_SocketContext.pIOCPSocketContext)).arg(((_GameUserData*)((*ii)->m_pClientExtraData))->m_strUserName));
        }
        Debug(_T("共(%1)个").arg(m_mapAllClients.count()));
    });

    connect(ui->pushButtonTick,&QPushButton::clicked,this,[=](){
        int context = ui->lineEditUserContextID->text().toInt();
        _ClientInfo *pClientInfo = m_mapAllClients.value((void*)context, nullptr);
        if(pClientInfo != nullptr)
        {
            m_Server.m_IOCPModel.Close(pClientInfo->m_SocketContext.nSocketID, pClientInfo->m_SocketContext.pIOCPSocketContext);
            Debug(_T("成功断开%1").arg((int)pClientInfo));
        }
        else
        {
            Debug(_T("没有%1").arg(context));
        }
    });

    //发送信息包
    connect(ui->pushButtonHeart,&QPushButton::clicked,this,[=](){

        int context = ui->lineEditUserContextID->text().toInt();
        _ClientInfo *pClientInfo = m_mapAllClients.value((void*)context, nullptr);
        if(pClientInfo != nullptr)
        {
            //_ClientInfo* pClientInfo = clientMap.value(pClientInfo->m_SocketContext.pIOCPSocketContext);
            m_Server.m_IOCPModel.sendData(pClientInfo) << ui->lineEditPacket->text();
            bool bRet = m_Server.m_IOCPModel.send(pClientInfo);
            Debug(_T("发送数据给用户%1(%2),返回%3").arg((int)pClientInfo->m_SocketContext.nSocketID).arg((int)pClientInfo->m_SocketContext.pIOCPSocketContext).arg(bRet));
            return;
        }
        else
        {
            Debug(_T("没有%1").arg(context));
        }
    });

    //IOCP池调试
    connect(ui->pushButtonDebug,&QPushButton::clicked,this,[=](){
        m_Server.m_IOCPModel.Debug(ui->lineEditDebugValue->text().toInt());
    });

    //本地调试信息
    connect(ui->pushButtonDebugCount,&QPushButton::clicked,this,[=](){
        Debug(_T("[DEBUG]Accepted(服务软件运行后总链接数):%1").arg(m_Server.m_nAcceptedCount));
        Debug(_T("[DEBUG]GroupPoolInfo(群数):%1,%2").arg(m_Server.m_poolClientsGroupInfo.m_listUsing.count()).arg(m_Server.m_poolClientsGroupInfo.m_listEmpty.count()));
        Debug(_T("[DEBUG]GroupCount(群数):%1").arg(m_Server.m_mapGroups.count()));
    });

    //清零统计
    connect(ui->pushButtonZero,&QPushButton::clicked,this,[=](){
        m_Server.m_nAcceptedCount = 0;
    });


    connect(&m_DatabaseSwap,&DatabaseSwap::s_Critical,this,[=](QString msg)
    {
        Critical(msg);
    });

    connect(&m_DatabaseSwap,&DatabaseSwap::s_Debug,this,[=](QString msg)
    {
        Debug(msg);
    });



    ui->lineEditPort->setText(m_Server.m_vmapConfig["ListenPort"].toString());
    m_ServerType = (_ServerType)m_Server.m_vmapConfig["ServerType"].toInt();
    m_nRecordUserOnlineLog = m_Server.m_vmapConfig["RecordUserOnlineLog"].toInt();

    //!server.listen(QHostAddress::Any,723);
/*
    Debug("");

    //查询所有数据
    QString strSQL = "select * from leamus_ylant_io";
    QSqlQuery sqlQuery(db);
    //sql_query.prepare(strSQL);  //有错误1/2：使用这个且
    if(!sqlQuery.exec(strSQL)) //有错误2/2：忽略参数
    {
        qDebug()<<"!"<<sqlQuery.lastError();
    }
    else
    {
        while(sqlQuery.next())
        {
            int id = sqlQuery.value(0).toInt();
            QString templ_name = sqlQuery.value(1).toString();
            qDebug()<<QString("Id:%1;Templ Name:%2").arg(id).arg(templ_name);
        }
    }
*/
    //emit ui->pushButtonStart->clicked();
    //qDebug() << "[Main Thread]QThread::currentThreadId()" << QThread::currentThreadId();
}

GameServer::~GameServer()
{
    Stop();
    delete ui;
    //m_DatabaseSwap.close();
}



bool GameServer::Start()
{
    if(m_DatabaseSwap.connectDB())
        Debug("[GameServer]连接数据库服务器成功");
    else
    {
        Critical("[!GameServer]连接数据库服务器失败!");
        return false;
    }

    m_Server.m_IOCPModel.SetServerPort(ui->lineEditPort->text().toInt());
    if(m_Server.Start() == false)
    {
        Critical("[!GameServer]服务器启动失败!");
        return false;
    }

    //加入0房间,表示不能有全0房间,
    m_hashNumberGroups.insert(0, nullptr);

    return true;
}

void GameServer::Stop()
{
    m_Server.Stop();
    m_DatabaseSwap.close();
    m_mapAllClients.clear();
    m_hashNumberGroups.clear();
}



int GameServer::ExitGroup(_ClientInfo *pClientInfo, bool groupWillClose)
{
    _ClientsGroupInfo *pGroup = pClientInfo->m_pGroup;
    _GameUserData *pGameUserData = (_GameUserData*)(pClientInfo->m_pClientExtraData);

    if(pGameUserData->m_GameStatus != _ClientGameStatus::Game_Waiting
            && pGameUserData->m_GameStatus != _ClientGameStatus::Game_Readying)
    {
        Warning(_T("[!GameServer]客户退出状态WARNING:%1").arg(pGameUserData->m_GameStatus));
        //return -5;
    }

    int ret = m_Server.ExitGroup(pClientInfo);

    //退群成功
    if(ret >= 0)
    {
        pGameUserData->m_GameStatus = _ClientGameStatus::Game_Nothing;
        Debug(_T("[GameServer]客户%1离开房间:%2").arg((int)pClientInfo).arg(pGroup->m_uuid.toString()));

        if(pClientInfo->m_bDisconnected == false)
        {
            //发送成功
            m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_RESPONSE
                                            << (qint16)GAME_SERVER_GROUP_EXITGROUP
                                            << (qint16)GAME_SERVER_GROUP_EXITGROUP_SUCCESS;
            m_Server.m_IOCPModel.send(pClientInfo);
        }


        if(groupWillClose == false)
        {
            //给群内其他客户发送
            QByteArray ba = pGroup->m_pIOCP->newSendData(0x10);
            QDataStream ds(&ba,QIODevice::ReadWrite);
            ds.device()->seek(ba.size());
            ds << (qint16)GAME_SERVER_RESPONSE
               << (qint16)GAME_SERVER_GROUP_OTHERSINFO
               << (qint16)GAME_SERVER_GROUP_OTHERSINFO_JOINGROUP
               << ((_GameUserData*)(pClientInfo->m_pClientExtraData))->m_strNickName
               << (bool)false
                  ;
            pGroup->m_pIOCP->CorrectDataLength(ba);
            pGroup->SendToGroupAllClients(ba, pClientInfo);


            //群里无人
            if(ret == 0)
            {
                QUuid groupID = pGroup->m_uuid;
                if(CloseGroup(pGroup) == 0) //关闭群
                {
                    m_Server.sendGroupInfoToAllClients(groupID,1);
                    Debug(_T("[GameServer]房间无人关闭:") + groupID.toString());
                }
                else
                    Critical(_T("[!GameServer]房间关闭出错:") + groupID.toString());

            }


            //如果房间内还有人,则结束游戏并发送
            if(pGroup->m_flagStatus & _ClientsGroupInfo::Status_Locked)
            {
                ((_GameGroup*)pGroup->m_pClientsGroupExtraData)->TerminateGame(-1, GameCore::Game_Status_Terminated);
            }


            //给群外客户发送
            m_Server.sendClientJoinInfoToAllClients(pClientInfo);
        }
    }
    else
    {
        if(pClientInfo->m_bDisconnected == false)
        {
            m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_RESPONSE
                                            << (qint16)GAME_SERVER_GROUP_EXITGROUP
                                            << (qint16)GAME_SERVER_GROUP_EXITGROUP_FAIL
                                            << (qint16)ret;
            m_Server.m_IOCPModel.send(pClientInfo);
        }

        Critical(_T("[!GameServer]客户离开房间失败:%1:").arg(ret));
    }
    return ret;
}



void GameServer::Message(QString msg)
{
    ui->textDebug->append(msg);
}

void GameServer::Debug(QString msg)
{
    ui->textDebug->append(msg);
    qDebug() << msg;
}

void GameServer::Warning(QString msg)
{
    ui->textDebug->append(msg);
    qWarning() << msg;
}

void GameServer::Critical(QString msg)
{
    ui->textDebug->append(msg);
    qCritical() << msg;
}



//池 实现
void GameServer::onAccept(_SocketInfo::_SocketContext socketContext)
{
    //qDebug() << "QThread::currentThreadId()" << QThread::currentThreadId();

    _ClientInfo *pClientInfo = (_ClientInfo *)socketContext.pSocketInfo;
    m_mapAllClients[socketContext.pIOCPSocketContext] = pClientInfo;
    //((_GameUserData*)pClientInfo->m_pClientExtraData)->_pool_init();

    //发送n个TransmitsCode
    m_Server.createTransmitsCodeAndSend(pClientInfo, TRANSMITS_CODE_COUNT);

    //pClientInfo->m_dtLogin = QDateTime::currentDateTime();

    Debug(_T("[GameServer]Accept:%1").arg((int)socketContext.pIOCPSocketContext));
}

//池 实现
void GameServer::onDisconnect(int type, _SocketInfo::_SocketContext socketContext)
{
    _ClientInfo *pClientInfo = (_ClientInfo *)socketContext.pSocketInfo;
    _GameUserData* pGameUserData = (_GameUserData*)pClientInfo->m_pClientExtraData;

    //m_mapAllClients.removeOne(pClientInfo);
    m_mapAllClients.remove(socketContext.pIOCPSocketContext);

    //登录 游戏服务器 的 用户
    if(pGameUserData->m_unUserGameID > 0)
    {
        DeductScore(pClientInfo);
        m_DatabaseSwap.insertUserOnlineLog(pGameUserData->m_unUserGameID, pClientInfo->m_nClientType, pClientInfo->m_dtLogin, QDateTime::currentDateTime());

    }

    if(m_ServerType == GameServer::Type_GameServer)
    {
    }
    if(m_nRecordUserOnlineLog != 0)
    {
    }

    _ClientsGroupInfo *pGroup = pClientInfo->m_pGroup;
    if(pGroup != nullptr)
    {
        ExitGroup(pClientInfo, false);
    }

    //((_GameUserData*)pClientInfo->m_pClientExtraData)->_pool_release();
    //pClientInfo->_pool_release();
    m_Server.m_IOCPModel.ReleaseSocketContext(socketContext.pIOCPSocketContext);

    Debug(_T("[GameServer]CloseSocket(%1):%2").arg(type).arg((int)socketContext.pIOCPSocketContext));
}

//非池 实现
/*
void GameServer::onAccept_NonPool(void *pIOCPSocketContext)
{
    _ClientInfo *pClientInfo = (_ClientInfo *)socketContext.pSocketInfo;
    m_mapAllClients[socketContext.pIOCPSocketContext] = pClientInfo;
    pClientInfo->m_pClientExtraData = new _GameUserData;

    //发送n个TransmitsCode
    m_Server.createTransmitsCodeAndSend(pClientInfo, TRANSMITS_CODE_COUNT);

    //pClientInfo->m_dtLogin = QDateTime::currentDateTime();

    Debug(_T("[GameServer]Accept:%1").arg((int)socketContext.pIOCPSocketContext));
}

//非池 实现
void GameServer::onDisconnect_NonPool(int type, _SocketInfo::_SocketContext socketContext)
{
    _ClientInfo *pClientInfo = (_ClientInfo *)socketContext.pSocketInfo;
    _GameUserData* pGameUserData = (_GameUserData*)pClientInfo->m_pClientExtraData;

    //m_mapAllClients.removeOne(pClientInfo);
    m_mapAllClients.remove(socketContext.pIOCPSocketContext);

    //登录 游戏服务器 的 用户
    if(pGameUserData->m_unUserGameID > 0)
    {
        DeductScore(pClientInfo);
        m_DatabaseSwap.insertUserOnlineLog(pGameUserData->m_unUserGameID, pClientInfo->m_nClientType, pClientInfo->m_dtLogin, QDateTime::currentDateTime());

    }

    if(m_ServerType == GameServer::Type_GameServer)
    {
    }
    if(m_nRecordUserOnlineLog != 0)
    {
    }


    _ClientsGroupInfo *pGroup = pClientInfo->m_pGroup;
    if(pGroup != nullptr)
    {
        //如果房间内还有人,则结束游戏并发送
        if(ExitGroup(pClientInfo) > 0)
            if(pGroup->m_flagStatus & _ClientsGroupInfo::Status_Locked)
            {
                ((_GameGroup*)pGroup->m_pClientsGroupExtraData)->TerminateGame(-1, GameCore::Game_Status_Terminated);
                //((_GameGroup*)pGroup->m_pClientsGroupExtraData)->wait();
            }
    }
    delete (_GameUserData*)pClientInfo->m_pClientExtraData;
    delete pClientInfo;


    Debug(_T("[GameServer]CloseSocket(%1):%2").arg(type).arg((int)socketContext.pIOCPSocketContext));
}
*/

void GameServer::onReadyRead(QByteArray baData, quint8 controlByte, _SocketInfo::_SocketContext socketContext)
{
    _ClientInfo *pClientInfo = (_ClientInfo *)socketContext.pSocketInfo;
    //qDebug()<<"ThreadId:"<<::GetCurrentThreadId();
    Debug(_T("[GameServer]Net Data Coming...:%1(%2)").arg(controlByte).arg(baData.length()));

    _GameUserData* pGameUserData = (_GameUserData*)pClientInfo->m_pClientExtraData;
    //QDataStream dsData(baData);   //ERROR!
    QDataStream dsData(&baData,QIODevice::ReadOnly);    //ReadWrite
    qint16 netType;

    //while(!dsData.atEnd())
    if(!dsData.atEnd())
    {
        //解密
        switch(controlByte)
        {
        case quint8(0x8d):
            if(pClientInfo->m_listInTransfersCode.length() > 0)
            {
                qint16 transfersCode = pClientInfo->m_listInTransfersCode.takeFirst();
                Debug(_T("[GameServer]读取密码:%1").arg(QString::fromLatin1(listTransfersCodeData.at(transfersCode % listTransfersCodeData.length()))));
                //showHex(baData.data(),baData.length());
                m_Server.recieveUseTransfersCode(pClientInfo, baData, listTransfersCodeData.at(transfersCode % listTransfersCodeData.length()));
                //showHex(baData.data(),baData.length());

                if(pClientInfo->m_listInTransfersCode.length() == 0)
                    m_Server.createTransmitsCodeAndSend(pClientInfo, TRANSMITS_CODE_COUNT);
            }
            else
            {
                Critical("[!GameServer]CodeList为空!");
                m_Server.recieveUseTransfersCode(pClientInfo, baData);
                return;
            }

            break;
        default:
            break;
        }

        /*
        QFile netLog("netLog.log");
        if(controlByte == 0x8d)
            netLog.setFileName("netsLog.log");
        netLog.open(QIODevice::Append);
        netLog.write(baData.toHex());
        netLog.write("\r\n--------------------------\r\n");
        netLog.close();
        */

        dsData >> netType;
        Debug(_T("[GameServer]Net Data Type:%1").arg(netType));
        switch(netType)
        {
        case INFO_SERVER_REQUEST:
            {
                dsData >> netType;
                switch(netType)
                {
                case INFO_SERVER_LOGIN:
                    {
                        int ret = 0;
                        QString password;
                        dsData >> pGameUserData->m_strUserName
                                >>password;
                        pGameUserData->m_strUserName = pGameUserData->m_strUserName.replace(QChar('\''),"");

                        //查找用户并且检查是否已经登录
                        ret = m_DatabaseSwap.queryUser(pClientInfo,password);
                        switch(ret)
                        {
                        case 0:
                            //pGameUserData->login = 1;   //UserData::login_IsLogined;

                            m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)INFO_SERVER_RESPONSE
                                                            << (qint16)INFO_SERVER_LOGIN
                                                            << (qint16)INFO_SERVER_LOGIN_SUCCESS
                                                            << (quint32)(pGameUserData->m_unID)
                                                            << (quint32)(pGameUserData->m_nGradeID);
                            m_Server.m_IOCPModel.send(pClientInfo);
                            /*
                            pClientInfo->dsOut << (quint32)0;
                            pClientInfo->dsOut << (qint16)GAME_SERVERRESPONSE << (qint16)GAME_SERVER_LOGIN << (qint16)GAME_SERVER_LOGIN_SUCCESS
                                           <<(quint32)(pGameUserData->id);
                            pClientInfo->dsOut.device()->seek(0);
                            pClientInfo->dsOut << pClientInfo->baOut.length() - sizeof(quint32);
                            */

                            Debug(_T("[GameServer]%1登录成功").arg(pGameUserData->m_strUserName));




                            //发送 游戏服务器 信息
                            m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)INFO_SERVER_RESPONSE
                                                                         <<(qint16)INFO_SERVER_SERVERINFO;

                            ret = m_DatabaseSwap.getGameServerInfoToBuffer(m_Server.m_IOCPModel.sendData(pClientInfo));
                            switch(ret) {
                            case 0:
                                Debug(_T("[GameServer]获取ServerInfo"));
                                break;
                            default:
                                {
                                    Critical(_T("[!GameServer]服务器{获取ServerInfo}ERROR:%1").arg(ret));
                                    m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)INFO_SERVER_SERVERINFO_FAIL;
                                }
                            }
                            m_Server.m_IOCPModel.send(pClientInfo);


                            break;
                        case 1:
                        case 2:
                            m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)INFO_SERVER_RESPONSE
                                                            << (qint16)INFO_SERVER_LOGIN
                                                            << (qint16)INFO_SERVER_LOGIN_FAIL
                                                            << (qint16)ret;
                            m_Server.m_IOCPModel.send(pClientInfo);
                            /*
                            pClientInfo->dsOut << (quint32)0;
                            pClientInfo->dsOut << (qint16)GAME_SERVERRESPONSE<<(qint16)GAME_SERVER_LOGIN<<(qint16)GAME_SERVER_LOGIN_FAIL
                                           << (qint16)ret;
                            pClientInfo->dsOut.device()->seek(0);
                            pClientInfo->dsOut << pClientInfo->baOut.length() - sizeof(quint32);
                            */
                            Debug(_T("[GameServer]%1登录失败").arg(pGameUserData->m_strUserName));
                            break;
                        default:
                            m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)INFO_SERVER_RESPONSE
                                                            << (qint16)INFO_SERVER_LOGIN
                                                            << (qint16)INFO_SERVER_LOGIN_FAIL
                                                            << (qint16)ret;
                            m_Server.m_IOCPModel.send(pClientInfo);

                            Critical(_T("[!GameServer]服务器{登录}ERROR:%1").arg(ret));
                            break;
                            /*
                            QList<TcpSocket*>::const_iterator ii;
                            for (ii = server.clientList.constBegin(); ii != server.clientList.constEnd(); ++ii)
                            {
                                if(((serverUserData*)((*ii)->data))->id == ((serverUserData*)(sock->data))->id
                                        && ((serverUserData*)((*ii)->data))->login == UserData::login_IsLogined)
                                {
                                    ret = -2;
                                    break;
                                }
                            }*/
                        }

                        /*
                        pClientInfo->dsOut.device()->reset();
                        pClientInfo->baOut.clear();*/
                    }
                    break;

                case INFO_SERVER_REGISTER:
                    {
                        QString password;
                        dsData >> pGameUserData->m_strUserName
                                >> pGameUserData->m_strNickName
                                >> password
                                >> pGameUserData->m_nSex;
                        pGameUserData->m_strUserName = pGameUserData->m_strUserName.replace(QChar('\''),"");
                        pGameUserData->m_strNickName = pGameUserData->m_strNickName.replace(QChar('\''),"");

                        int ret = m_DatabaseSwap.registerUser(pClientInfo,password);
                        switch(ret)
                        {
                        case 0:
                            m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)INFO_SERVER_RESPONSE
                                                            << (qint16)INFO_SERVER_REGISTER
                                                            << (qint16)INFO_SERVER_REGISTER_SUCCESS;

                            Debug(_T("[GameServer]%1注册成功").arg(pGameUserData->m_strUserName));
                            break;
                        case 1:
                            m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)INFO_SERVER_RESPONSE
                                                            <<(qint16)INFO_SERVER_REGISTER
                                                           <<(qint16)INFO_SERVER_REGISTER_FAIL
                                                          <<(qint16)ret;
                            Debug(_T("[GameServer]%1注册失败").arg(pGameUserData->m_strUserName));
                            break;
                        default:
                            m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)INFO_SERVER_RESPONSE
                                                            <<(qint16)INFO_SERVER_REGISTER
                                                           <<(qint16)INFO_SERVER_REGISTER_FAIL
                                                          <<(qint16)ret;
                            Critical(_T("[!GameServer]服务器{注册}ERROR:%1").arg(ret));
                        }
                        m_Server.m_IOCPModel.send(pClientInfo);
                    }
                    break;

                    /*
                case INFO_SERVER_SERVERINFO:
                    {
                        m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)INFO_SERVER_RESPONSE
                            <<(qint16)INFO_SERVER_SERVERINFO;

                        int ret = m_DatabaseSwap.getGameServerInfoToBuffer(m_Server.m_IOCPModel.sendData(pClientInfo));
                        switch(ret) {
                        case 0:
                            Debug(_T("[GameServer]获取ServerInfo"));
                            break;
                        default:
                            {
                                Critical(_T("[!GameServer]服务器{获取ServerInfo}ERROR:%1").arg(ret));
                                m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)INFO_SERVER_SERVERINFO_FAIL;
                            }
                        }
                        m_Server.m_IOCPModel.send(pClientInfo);
                    }
                    break;
                    */
                default:
                    Critical(_T("[!GameServer]数据总类型未识别3:%1").arg(netType));
                    break;
                }
            }
            break;
        case GAME_SERVER_REQUEST:
            {
                dsData >> netType;
                switch(netType)
                {
                //注册玩家号,废弃!!
                case GAME_SERVER_REGISTERGAMEUSERINFO:
                    {
                        _GameUserData* pGameUserData = (_GameUserData*)pClientInfo->m_pClientExtraData;

                        quint32 userID;
                        quint32 serverID;
                        QString nickName;
                        qint16 sex;
                        dsData >> userID >> serverID >> nickName >> sex;

                        m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_RESPONSE
                            <<(qint16)GAME_SERVER_REGISTERGAMEUSERINFO;

                        int ret = m_DatabaseSwap.registerGameUser(userID, serverID, nickName, sex, m_Server.m_IOCPModel.sendData(pClientInfo), pClientInfo);
                        switch(ret)
                        {
                        case 0:
                            {
                                Debug(_T("[GameServer]注册玩家信息成功:%1").arg(pGameUserData->m_strNickName));
                                break;
                            }
                        case 1:
                            {
                                Debug(_T("[GameServer]RegGameUserInfo重复"));
                                m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_REGISTERGAMEUSERINFO_FAIL
                                  <<(qint16)1;
                            }
                            break;
                        default:
                            {
                                Critical(_T("[!GameServer]服务器{RegGameUserInfo}ERROR:%1").arg(ret));
                                m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_REGISTERGAMEUSERINFO_FAIL
                                  <<(qint16)ret;
                            }
                        }
                        m_Server.m_IOCPModel.send(pClientInfo);
                    }
                    break;
                //获取玩家信息
                case GAME_SERVER_GAMEUSERINFO:
                    {
                        _GameUserData* pGameUserData = (_GameUserData*)pClientInfo->m_pClientExtraData;

                        quint32 userID;
                        quint32 serviceID;
                        quint32 gradeID;
                        qint16 clientType;
                        QString serverKey;
                        dsData >> userID >> serviceID >> gradeID >> serverKey >> clientType;

                        pClientInfo->m_nClientType = clientType;

                        m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_RESPONSE
                            <<(qint16)GAME_SERVER_GAMEUSERINFO;

                        int ret = m_DatabaseSwap.getGameUserInfoToBuffer(m_Server.m_IOCPModel.sendData(pClientInfo), userID, serviceID, gradeID, serverKey, pClientInfo);
                        switch(ret)
                        {
                        case 0:
                            Debug(_T("[GameServer]获取GameUserInfo:%1").arg(pGameUserData->m_strNickName));
                            break;
                        case 1:
                            m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_GAMEUSERINFO_FAIL
                                                            << (qint16)ret;
                            Debug(_T("[GameServer]需要注册GameUserInfo"));
                            break;
                        default:
                            m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_GAMEUSERINFO_FAIL
                                                            << (qint16)ret;
                            Critical(_T("[!GameServer]服务器{获取GameUserInfo}ERROR:%1").arg(ret));
                        }
                        m_Server.m_IOCPModel.send(pClientInfo);
                    }
                    break;

                //可取所有课程信息
                case GAME_SERVER_CLASSINFO:
                    {
                        m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_RESPONSE
                            <<(qint16)GAME_SERVER_CLASSINFO;

                        int ret = m_DatabaseSwap.getGameClassInfoToBuffer(m_Server.m_IOCPModel.sendData(pClientInfo));
                        switch(ret)
                        {
                        case 0:
                            Debug(_T("[GameServer]获取ClassInfo"));
                            break;
                        default:
                            Critical(_T("[!GameServer]服务器{获取ClassInfo}ERROR:%1").arg(ret));
                            m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_CLASSINFO_FAIL
                                                            << (qint16)ret;
                        }
                        m_Server.m_IOCPModel.send(pClientInfo);

                        //qDebug()<<"------------------ClassCount:";
                        //showHex(pClientInfo->baOut.data(),pClientInfo->baOut.length());
                        //qDebug()<<"------------------ClassCount------------";
                    }
                    break;
                //获取所有玩家学习记录
                case GAME_SERVER_STUDYINFO:
                    {
                        //quint32 userGameID;
                        //dsData >> userGameID;
                        _GameUserData* pGameUserData = (_GameUserData*)pClientInfo->m_pClientExtraData;

                        m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_RESPONSE
                            <<(qint16)GAME_SERVER_STUDYINFO;

                        int ret = m_DatabaseSwap.getGameUserStudyInfoToBuffer(m_Server.m_IOCPModel.sendData(pClientInfo),pGameUserData->m_unUserGameID);
                        switch(ret)
                        {
                        case 0:
                            Debug(_T("[GameServer]获取StudyInfo"));
                            break;
                        default:
                            Critical(_T("[!GameServer]服务器{获取StudyInfo}ERROR:%1").arg(ret));
                            m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_STUDYINFO_FAIL
                                                            << (qint16)ret;
                        }
                        m_Server.m_IOCPModel.send(pClientInfo);
                    }
                    break;
                //保存学习记录
                case GAME_SERVER_SAVESTUDYINFO:
                    {
                        _GameUserData* pGameUserData = (_GameUserData*)pClientInfo->m_pClientExtraData;

                        //quint32 userGameID;
                        //qint16 type;
                        quint32 classID;
                        quint32 levelID;
                        QString result;

                        dsData /*>> type*/ >> classID >> levelID >> result;

                        qint16 ret = m_DatabaseSwap.saveUserStudyResult(pGameUserData->m_unUserGameID
                                                         //,type
                                                         ,classID
                                                         ,levelID
                                                         ,result
                                                         );

                        m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_RESPONSE
                            <<(qint16)GAME_SERVER_SAVESTUDYINFO;
                        switch(ret)
                        {
                        case 0:
                            {
                                Debug(_T("[GameServer]SaveStudyInfo UPDATE"));
                                m_Server.m_IOCPModel.sendData(pClientInfo)<<(qint16)GAME_SERVER_SAVESTUDYINFO_SUCCESS
                                                              <<(qint16)ret;
                            }
                            break;
                        case 1:
                            {
                                Debug(_T("[GameServer]SaveStudyInfo INSERT"));
                                m_Server.m_IOCPModel.sendData(pClientInfo)<<(qint16)GAME_SERVER_SAVESTUDYINFO_SUCCESS
                                                              <<(qint16)ret<<classID<<levelID;
                            }
                            break;
                        default:
                            {
                                Critical(_T("[!GameServer]服务器{SaveStudyInfo}ERROR:%1").arg(ret));
                                m_Server.m_IOCPModel.sendData(pClientInfo)<<(qint16)GAME_SERVER_SAVESTUDYINFO_FAIL
                                                              <<(qint16)ret;
                            }
                        }
                        m_Server.m_IOCPModel.send(pClientInfo);
                        //return ret;
                    }
                    break;
                //更新积分
                case GAME_SERVER_UPDATESCORE:
                    {
                        _GameUserData* pGameUserData = (_GameUserData*)pClientInfo->m_pClientExtraData;

                        //quint32 userGameID;
                        qint32 scoreAdd;
                        dsData >> scoreAdd;
                        int ret = m_DatabaseSwap.updateUserScore(pGameUserData->m_unUserGameID, scoreAdd);

                        m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_RESPONSE
                            <<(qint16)GAME_SERVER_UPDATESCORE;
                        switch(ret)
                        {
                        case 0:
                            Debug(_T("[GameServer]UpdateScore"));
                            m_Server.m_IOCPModel.sendData(pClientInfo)<<(qint16)GAME_SERVER_UPDATESCORE_SUCCESS;
                            break;
                        default:
                            Critical(_T("[!GameServer]服务器{UpdateScore}ERROR:%1").arg(ret));
                            m_Server.m_IOCPModel.sendData(pClientInfo)<<(qint16)GAME_SERVER_UPDATESCORE_FAIL
                                                          <<(qint16)ret;
                        }
                        m_Server.m_IOCPModel.send(pClientInfo);
                        //return ret;
                    }
                    break;
                //获取排名
                case GAME_SERVER_RANKING:
                    {
                        quint32 serverID;
                        quint32 gradeID;
                        dsData >> serverID >> gradeID;

                        m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_RESPONSE
                            <<(qint16)GAME_SERVER_RANKING;

                        int ret = m_DatabaseSwap.getGameUserRankingToBuffer(m_Server.m_IOCPModel.sendData(pClientInfo), serverID, gradeID);
                        switch(ret)
                        {
                        case 0:
                            Debug(_T("[GameServer]获取Ranking"));
                            break;
                        default:
                            Critical(_T("[!GameServer]服务器{获取Ranking}ERROR:%1").arg(ret));
                            m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_RANKING_FAIL
                                                                << (qint16)ret;
                        }
                        m_Server.m_IOCPModel.send(pClientInfo);

                        //qDebug()<<"------------------ClassCount:";
                        //showHex(pClientInfo->baOut.data(),pClientInfo->baOut.length());
                        //qDebug()<<"------------------ClassCount------------";
                    }
                    break;

                case GAME_SERVER_ITEMS:
                    {
                        quint32 serverID;
                        dsData >> serverID;

                        _GameUserData *pGameUserData = (_GameUserData*)(pClientInfo->m_pClientExtraData);

                        m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_RESPONSE
                            <<(qint16)GAME_SERVER_ITEMS;

                        int ret = m_DatabaseSwap.getGameUserItemsToBuffer(m_Server.m_IOCPModel.sendData(pClientInfo), pGameUserData, serverID);
                        switch(ret)
                        {
                        case 0:
                            Debug(_T("[GameServer]获取Items"));
                            break;
                        default:
                            Critical(_T("[!GameServer]服务器{获取Items}ERROR:%1").arg(ret));
                            m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_ITEMS_FAIL
                                                                << (qint16)ret;
                        }
                        m_Server.m_IOCPModel.send(pClientInfo);

                        //qDebug()<<"------------------ClassCount:";
                        //showHex(pClientInfo->baOut.data(),pClientInfo->baOut.length());
                        //qDebug()<<"------------------ClassCount------------";
                    }
                    break;




            //房间功能
                //创建房间
                case GAME_SERVER_GROUP_CREATE:
                    {
                        qint16 playerMaxCount;
                        QString password;
                        quint32 classID;
                        dsData >> playerMaxCount >> password >> classID;

                        m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_RESPONSE
                                                        <<(qint16)GAME_SERVER_GROUP_CREATE;

                        if(pClientInfo->m_pGroup != nullptr)
                        {
                            Critical(_T("[!GameServer]用户已经进入了一个房间!"));
                            m_Server.m_IOCPModel.sendData(pClientInfo)<<(qint16)GAME_SERVER_GROUP_CREATE_FAIL<<
                                                             (qint16)-1;
                            m_Server.m_IOCPModel.send(pClientInfo);
                        }
                        else
                        {
                            _ClientsGroupInfo *pGroup = nullptr;
                            qint32 groupID = CreateGroupHashID(6);
                            groupID = CreateGroup(playerMaxCount,password,groupID);

                            if(groupID < 0)
                                Critical(_T("[!GameServer]创建房间失败:%1").arg(groupID));
                            else
                                pGroup = m_hashNumberGroups.value(groupID, nullptr);

                            if(pGroup != nullptr)
                            {
                                //_GameGroup *p = new _GameGroup;
                                //_GameGroup *p = m_poolGameGroup.getOneEmpty();
                                //pGroup->m_pClientsGroupExtraData = p;
                                _GameGroup *p = (_GameGroup*)pGroup->m_pClientsGroupExtraData;
                                if(p->_pool_newNode())  //如果是新节点
                                {
                                    p->m_pClientsGroupInfo = pGroup;
                                    connect(p,&GameCore::s_Message,this,&GameServer::Message);
                                    connect(p,&GameCore::s_Debug,this,&GameServer::Debug);
                                    connect(p,&GameCore::s_Critical,this,&GameServer::Critical);

                                    //qRegisterMetaType<QByteArray>("QByteArray");      //qml中使用其函数
                                    connect(p,&_GameGroup::s_SendToGroupAllClients,
                                            p,&_GameGroup::SendToGroupAllClients);

                                    connect(p,&GameCore::s_GameOver,p,_GameGroup::OverGame);
                                    p->_pool_setNewNode(false);
                                }
                                p->m_unClassID = classID;


                                int ret = JoinGroup(pClientInfo,pGroup,password);
                                if(ret >= 0)
                                {
                                    Debug(_T("[GameServer]创建一个房间并加入成功:%1(%2)").arg(groupID).arg(pGroup->m_uuid.toString()));
                                    m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_GROUP_CREATE_SUCCESS
                                                                             << groupID;
                                    m_Server.m_IOCPModel.send(pClientInfo);
                                    m_Server.sendGroupInfoToAllClients(pGroup);
                                }
                                else
                                {
                                    Critical(_T("[!GameServer]创建房间成功,加入失败:%1").arg(ret));
                                    m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_GROUP_CREATE_FAIL
                                                                      << (qint16)ret;
                                    m_Server.m_IOCPModel.send(pClientInfo);
                                    CloseGroup(pGroup);
                                }
                            }
                            else
                            {
                                Critical(_T("[!GameServer]创建一个房间失败:%1").arg(groupID));
                                m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_GROUP_CREATE_FAIL
                                                                  << (qint16)groupID;
                                m_Server.m_IOCPModel.send(pClientInfo);
                            }
                        }
                    }
                    break;

                case GAME_SERVER_GROUP_CLOSE:
                    break;

                case GAME_SERVER_GROUP_UPDATE:
                    break;

                //退房间
                case GAME_SERVER_GROUP_EXITGROUP:
                    {
                        _ClientsGroupInfo *pGroup = pClientInfo->m_pGroup;
                        if(pGroup != nullptr)
                        {
                            ExitGroup(pClientInfo, false);
                        }
                    }
                    break;

                //群消息
                case GAME_SERVER_GROUP_MESSAGE:
                    {
                        qint16 type;
                        qint16 seatID;
                        QString message;
                        dsData >> type >> seatID >> message;
                        if(pClientInfo->m_pGroup != nullptr)
                        {
                            //发送
                            QByteArray ba = pClientInfo->m_pGroup->m_pIOCP->newSendData(0x10);
                            QDataStream ds(&ba,QIODevice::ReadWrite);
                            ds.device()->seek(ba.size());
                            ds << (qint16)GAME_SERVER_RESPONSE
                               << (qint16)GAME_SERVER_GROUP_OTHERSINFO
                               << (qint16)GAME_SERVER_GROUP_OTHERSINFO_MESSAGE
                               << (qint16)type
                               << (qint16)seatID
                               << message
                                  ;
                            pClientInfo->m_pGroup->m_pIOCP->CorrectDataLength(ba);
                            pClientInfo->m_pGroup->SendToGroupAllClients(ba, pClientInfo);

                        }
                    }
                    break;

                //加入房间
                case GAME_SERVER_GROUP_JOINGROUP:
                    {
                        qint32 groupID;
                        QString password;

                        _GameUserData *pGameUserData = (_GameUserData*)(pClientInfo->m_pClientExtraData);

                        dsData >> groupID >> password;

                        m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_RESPONSE
                                                        <<(qint16)GAME_SERVER_GROUP_JOINGROUP;

                        int ret = JoinGroup(pClientInfo, groupID, password);

                        if(ret >= 0)
                        {
                            //_ClientsGroupInfo *pGroup = m_hashNumberGroups.value(groupID, nullptr);

                            //获得真实groupID(因为有可能是随机加入房间,groupID为0)
                            groupID = ((_GameGroup*)pClientInfo->m_pGroup->m_pClientsGroupExtraData)->m_nGroupID;

                            m_Server.m_IOCPModel.sendData(pClientInfo)<<(qint16)GAME_SERVER_GROUP_JOINGROUP_SUCCESS
                                                                       << groupID;
                            m_Server.m_IOCPModel.send(pClientInfo);



                            //发送
                            QByteArray ba = pClientInfo->m_pGroup->m_pIOCP->newSendData(0x10);
                            QDataStream ds(&ba,QIODevice::ReadWrite);
                            ds.device()->seek(ba.size());
                            ds << (qint16)GAME_SERVER_RESPONSE
                               << (qint16)GAME_SERVER_GROUP_OTHERSINFO
                               << (qint16)GAME_SERVER_GROUP_OTHERSINFO_JOINGROUP
                               << pGameUserData->m_strNickName
                               << (bool)true
                                  ;
                            pClientInfo->m_pGroup->m_pIOCP->CorrectDataLength(ba);
                            pClientInfo->m_pGroup->SendToGroupAllClients(ba, pClientInfo);


                            m_Server.sendClientJoinInfoToAllClients(pClientInfo);
                            Debug(_T("[GameServer]客户加入房间:%1").arg(groupID));
                        }
                        else
                        {
                            m_Server.m_IOCPModel.sendData(pClientInfo)<<(qint16)GAME_SERVER_GROUP_JOINGROUP_FAIL<<
                                                             (qint16)ret;
                            m_Server.m_IOCPModel.send(pClientInfo);
                            Critical(_T("[!GameServer]客户加入房间失败:%1").arg(ret));
                        }
                        //return ret;
                    }
                    break;

                //准备
                case GAME_SERVER_GROUP_GETREADY:
                    {
                        _GameUserData *pGameUserData = (_GameUserData*)(pClientInfo->m_pClientExtraData);

                        dsData >> pGameUserData->m_nDuiWu;
                        m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_RESPONSE
                                                        <<(qint16)GAME_SERVER_GROUP_GETREADY;

                        int ret = -2;
                        //判断原来是否有房间
                        if(pClientInfo->m_pGroup != nullptr)
                            ret = pGameUserData->ChangeGameStatus();

                        switch (ret)
                        {
                        case 0:
                            {
                                m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_GROUP_GETREADY_SUCCESS
                                                                << (qint16)pGameUserData->m_GameStatus;
                                m_Server.m_IOCPModel.send(pClientInfo);


                                //发送
                                QByteArray ba = pClientInfo->m_pGroup->m_pIOCP->newSendData(0x10);
                                QDataStream ds(&ba,QIODevice::ReadWrite);
                                ds.device()->seek(ba.size());
                                ds << (qint16)GAME_SERVER_RESPONSE
                                   << (qint16)GAME_SERVER_GROUP_OTHERSINFO
                                   << (qint16)GAME_SERVER_GROUP_OTHERSINFO_READY
                                   << pGameUserData->m_strNickName
                                   << (qint16)pGameUserData->m_GameStatus
                                   << pGameUserData->m_nDuiWu
                                      ;
                                pClientInfo->m_pGroup->m_pIOCP->CorrectDataLength(ba);
                                pClientInfo->m_pGroup->SendToGroupAllClients(ba, pClientInfo);


                                m_Server.sendClientReadyInfoToAllClients(pClientInfo);

                                Debug(_T("[GameServer]客户切换状态成功:%1").arg(pGameUserData->m_GameStatus));
                                break;
                            }
                        case -1:
                            m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_GROUP_GETREADY_FAIL
                                                            << (qint16)pGameUserData->m_GameStatus;
                            m_Server.m_IOCPModel.send(pClientInfo);
                            Critical(_T("[!GameServer]客户切换状态失败1:%1").arg(pGameUserData->m_GameStatus));
                            break;
                        default:
                            m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_GROUP_GETREADY_FAIL
                                                            << (qint16)ret;
                            m_Server.m_IOCPModel.send(pClientInfo);
                            Critical(_T("[!GameServer]客户切换状态失败2:%1").arg(ret));
                            break;
                        }


                        //QByteArray ba = m_IOCPModel.newSendData(0x10);
                        //QDataStream ds(&ba,QIODevice::ReadWrite);
                        //ds.device()->seek(ba.size());

                        //m_pClientsGroupInfo->m_pIOCP->CorrectDataLength(ba);
                        //pClientInfo->m_pGroup->SendToGroupAllClients(ds, pClientInfo);
                        ////sendToAllClientInGroup(ba, pClientInfo);

                    }
                    break;


            //游戏控制
                //游戏开始
                case GAME_SERVER_STARTGAME:
                    {
                        int ret;
                        if(pClientInfo == nullptr)
                            ret = -10;
                        else
                        {
                            if(pClientInfo->m_pGroup == nullptr)   //单人游戏
                            {
                                pGameUserData->m_GameStatus = _ClientGameStatus::Game_Playing;
                                break;
                            }
                            else    //多人游戏
                                ret = ((_GameGroup*)pClientInfo->m_pGroup->m_pClientsGroupExtraData)->StartGame();
                        }

                        switch (ret)
                        {
                        case 0:
                            {
                                //pClientInfo->m_pGroup->StartGame(pClientInfo);
                                Debug(_T("[GameServer]游戏开始!"));
                            }
                            break;
                        default:
                            m_Server.m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_RESPONSE
                                                            << (qint16)GAME_SERVER_STARTGAME
                                                            << (qint16)GAME_SERVER_STARTGAME_FAIL
                                                            << (qint16)ret;
                            m_Server.m_IOCPModel.send(pClientInfo);
                            break;
                        }

                    }
                    break;
                //游戏初始化结束
                case GAME_SERVER_INITOVER:
                    {
                        quint32 gameID;
                        dsData >> gameID;

                        if(pClientInfo == nullptr || pClientInfo->m_pGroup == nullptr)
                            break;

                        int uninitCount = 0;
                        QList<_ClientInfo*>::const_iterator ii;
                        for(ii = pClientInfo->m_pGroup->m_listClients.constBegin(); ii != pClientInfo->m_pGroup->m_listClients.constEnd(); ++ii)
                        {
                            if(gameID == ((_GameUserData*)((*ii)->m_pClientExtraData))->m_unUserGameID)
                            {
                                ((_GameUserData*)((*ii)->m_pClientExtraData))->m_GameStatus = _ClientGameStatus::Game_Playing;
                                continue;
                            }
                            else
                            {
                                if(((_GameUserData*)((*ii)->m_pClientExtraData))->m_GameStatus == _ClientGameStatus::Game_Playing)
                                    continue;
                                else
                                {
                                    uninitCount++;
                                }
                            }
                        }

                        if(uninitCount == 0)
                            ((_GameGroup*)pClientInfo->m_pGroup->m_pClientsGroupExtraData)->start();
                        else
                            Debug(_T("[GameServer]还缺客户Init:%1").arg(uninitCount));
                    }
                    break;


                //游戏结束
                case GAME_SERVER_GAMEOVER:
                    {
                        bool bTerminate;        //是否是强制结束的
                        dsData >> bTerminate;

                        if(pClientInfo == nullptr)
                            break;

                        //if(bTerminate)    //客户端主动发送扣的分数
                        //    DeductScore(pClientInfo);

                        if(pClientInfo->m_pGroup == nullptr)   //单人
                        {
                            pGameUserData->m_GameStatus = Game_Nothing;
                        }
                        else    //联网,则强制结束游戏
                        {
                            pGameUserData->m_GameStatus = Game_Waiting;
                            ((_GameGroup*)pClientInfo->m_pGroup->m_pClientsGroupExtraData)->TerminateGame(-1, GameCore::Game_Status_Terminated);
                        }

                        //if(pClientInfo->m_pGroup == nullptr)
                        //    pGameUserData->m_GameStatus = Game_Nothing;
                        //else
                        {
                            //pGameUserData->m_GameStatus = Game_Waiting;
                        }

                    }
                    break;

                /*
                //强制退出游戏
                case GAME_SERVER_TERMINATEGAME:
                    {
                        Debug(_T("[GameServer]强制退出"));
                        if(pClientInfo == nullptr)
                            break;

                        DeductScore(pClientInfo);

                        if(pClientInfo->m_pGroup == nullptr)   //单人
                            pGameUserData->m_GameStatus = Game_Nothing;
                        else    //联网
                        {
                            pGameUserData->m_GameStatus = Game_Waiting;
                            ((_GameGroup*)pClientInfo->m_pGroup->m_pClientsGroupExtraData)->TerminateGame(-1);
                        }

                    }
                    break;
                */
                /*
                case GAME_SERVER_:
                    {
                        //dsData >> var;
                        m_IOCPModel.sendData(pClientInfo) << (qint16)GAME_SERVER_RESPONSE
                                                        <<(qint16)GAME_SERVER_GROUP_EXITGROUP;
                    }
                    break;
                    */

                default:
                    Critical(_T("[!GameServer]数据总类型未识别2:%1").arg(netType));
                    break;
                }
            }
            break;


        case GAME_DATA:
            {
                _GameGroup *pGameGroup = ((_GameGroup*)pClientInfo->m_pGroup->m_pClientsGroupExtraData);
                if(pClientInfo == nullptr || pClientInfo->m_pGroup == nullptr)
                {
                    Warning(_T("[!GameServer]WARNING!指针为nullptr:%1,%2").arg((int)pClientInfo).arg((int)pClientInfo->m_pGroup));
                    return;
                }
                if(!(pClientInfo->m_pGroup->m_flagStatus & _ClientsGroupInfo::Status_Locked))
                {
                    Warning(_T("[!GameServer]WARNING!接收GAME包时Group状态为Unlocked:%1").arg(pClientInfo->m_pGroup->m_flagStatus));
                    return;
                }
                if(pGameGroup->gameStatus() != GameCore::Game_Status_Continue)
                {
                    Warning(_T("[!GameServer]WARNING!接收GAME包时Game已经结束:%1").arg(pGameGroup->gameStatus()));
                    return;
                }

                dsData >> netType;
                Debug(_T("[GameServer]GAME_DATA:%1").arg(netType));
                switch(netType)
                {
                case GAME_DATA_TRANSFER_CHOICEWUJIANG:
                    {
                        _GameUserData *pGameUserData = (_GameUserData*)(pClientInfo->m_pClientExtraData);

                        _GameData *pData = new _GameData;
                        if(pData == nullptr)
                        {
                            pGameGroup->TerminateGame(-10, GameCore::Game_Status_ERROR);
                            return;
                        }

                        pData->sender = pClientInfo;
                        pData->type = netType;

                        qint16 wujiang;
                        dsData >> wujiang;

                        pGameGroup->m_arrayPlayer[pGameUserData->m_nPlayID].getWuJiang((_WuJiang::_Value)wujiang, 0);

                        if(!pData->CheckGameData())
                        {
                            if(pData != nullptr)delete pData;
                            pGameGroup->TerminateGame(-11, GameCore::Game_Status_ERROR);
                            return;
                        }

                        Debug(_T("[GameServer]武将选择接受保存到队列"));
                        pGameGroup->m_Producer.safeIn(pData);
                        Debug(_T("[GameServer]武将选择接受完毕"));
                    }
                    break;
                case GAME_DATA_TRANSFER_CHUPAI:
                    {
                        //qDebug()<<"接收到转发数据类型:"<<data;
                        _GameData *pData = new _GameData;
                        if(pData == nullptr)
                        {
                            pGameGroup->TerminateGame(-20 ,GameCore::Game_Status_ERROR);
                            return;
                        }

                        pData->sender = pClientInfo;
                        pData->type = netType;

                        dsData >> pData->ChuPaiData.nData;
                        dsData >> pData->ChuPaiData.nDataLength;
                        if(!pData->CheckGameData())
                        {
                            if(pData != nullptr)delete pData;
                            pGameGroup->TerminateGame(-21, GameCore::Game_Status_ERROR);
                            return;
                        }
                        pData->ChuPaiData.pData = new char[pData->ChuPaiData.nDataLength];
                        if(pData->ChuPaiData.pData == nullptr)
                        {
                            delete pData;
                            pGameGroup->TerminateGame(-22, GameCore::Game_Status_ERROR);
                            return;
                        }
                        int ret = dsData.readRawData(pData->ChuPaiData.pData,pData->ChuPaiData.nDataLength);
                        if(ret != pData->ChuPaiData.nDataLength)
                        {
                            Critical(_T("[!GameServer]GameData读取数据出错:%1").arg(ret));

                            delete pData->ChuPaiData.pData;
                            delete pData;
                            pGameGroup->TerminateGame(-23, GameCore::Game_Status_ERROR);
                            return;
                        }

                        Debug(_T("[GameServer]出牌接受保存到队列"));
                        pGameGroup->m_Producer.safeIn(pData);
                        Debug(_T("[GameServer]出牌接受完毕"));
                        //qDebug()<<"接收处理完毕:"<<data;
                    }
                    break;
                case GAME_DATA_TRANSFER_ANSWER:
                    {
                        _GameData *pData = new _GameData;
                        if(pData == nullptr)
                        {
                            pGameGroup->TerminateGame(-30, GameCore::Game_Status_ERROR);
                            return;
                        }

                        pData->sender = pClientInfo;
                        pData->type = netType;

                        dsData >> pData->nAnswer;

                        if(!pData->CheckGameData())
                        {
                            if(pData != nullptr)delete pData;
                            pGameGroup->TerminateGame(-31, GameCore::Game_Status_ERROR);
                            return;
                        }

                        Debug(_T("[GameServer]回答接受保存到队列"));
                        pGameGroup->m_Producer.safeIn(pData);
                        Debug(_T("[GameServer]回答接受完毕"));
                    }
                    break;

                /*
                case GAME_DATA_GAMESTART:
                    {
                        _GameGroup *pGroup = (_GameGroup*)pClientInfo->m_pGroup->m_pClientsGroupExtraData;
                        //传递所有武将信息！！！
                        dsData >> netType;
                        pGroup->m_nMyID = netType;
                        dsData >> netType;
                        pGroup->m_nPlayerCount = netType;
                        dsData>>pGroup->m_bMaster;

                        QList<qint16> playerTypeList;
                        dsData>>playerTypeList;

                        int i = 0;
                        for(i = 0; i < playerTypeList.count(); i++)
                        {
                            pGroup->m_arrayPlayer[i].m_eJiaoSe = (_Player::JiaoSe)playerTypeList[i];
                        }
                        / *
                        QList<qint16>::iterator ii;
                        for (ii = playerTypeList.begin(); ii != playerTypeList.end(); ++ii)
                        {
                               pClientInfo->m_pGroup->m_arrayPlayer[i].iJiaoSe = *ii;
                        }* /

                        //pClientInfo->m_pGroup->netPlay = true;

                        qDebug()<<"StartGame:"
                               <<pGroup->m_nMyID
                              <<pGroup->m_nPlayerCount
                             <<pGroup->m_bMaster;

                        //StartGame(pClientInfo->m_pGroup->m_nPlayerCount,1,1,0,true);
                    }
                    break;
                case GAME_DATA_GAMEOVER:
                    {
                        dsData >> netType;
                        //GameOver((GameCore::_GameStatus)netType);
                    }
                    break;
                */

                default:
                    Critical(_T("[!GameServer]数据总类型未识别1:%1").arg(netType));
                    break;
                }
            }
            break;


        default:
            Critical(_T("[!GameServer]数据总类型未识别0:%1").arg(netType));
            break;
        }
    }
    return;
}
